#pragma once 
#include <bits/stdc++.h>


//! 将个各种可调用对象转化成std::function

//转换为std::function和函数指针. 
template<typename T>
struct function_traits;

//普通函数.
template<typename Ret, typename... Args>
struct function_traits<Ret(Args...)> {
public:
	enum { arity = sizeof...(Args) };
	typedef Ret function_type(Args...);
	typedef Ret return_type;
	using stl_function_type = std::function<function_type>;
	typedef Ret(*pointer)(Args...);

	template<size_t I>
	struct args {
		static_assert(I < arity, "index is out of range, index must less than sizeof Args");
		using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
	};
	
	typedef std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> tuple_type;
	typedef std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...> bare_tuple_type;
};

//函数指针.
template<typename Ret, typename... Args>
struct function_traits<Ret(*)(Args...)> : function_traits<Ret(Args...)>{};

//std::function.
template <typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> : function_traits<Ret(Args...)>{};

//member function.
#define FUNCTION_TRAITS(...)\
template <typename ReturnType, typename ClassType, typename... Args>\
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)>{};\

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

//函数对象.
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())>{};

template <typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda) {
	return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}

template <typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda) {
	return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}

template <typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda) {
	return static_cast<typename function_traits<Function>::pointer>(lambda);
}

class NonCopyable {
public:
    // 使用默认无参构造函数
    NonCopyable() = default;

    //! 禁用拷贝构造函数 
    NonCopyable(const NonCopyable& rhs)            = delete;
    
    //! 禁用赋值函数 
    NonCopyable& operator=(const NonCopyable& rhs) = delete;
};


struct Any {
	Any(void) : m_tpIndex(std::type_index(typeid(void))) {}
	Any(const Any& that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
	Any(Any && that) : m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}

	//创建智能指针时，对于一般的类型，通过std::decay来移除引用和cv符，从而获取原始类型
	template<typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type> Any(U && value) : m_ptr(new Derived < typename std::decay<U>::type>(std::forward<U>(value))),
		m_tpIndex(std::type_index(typeid(typename std::decay<U>::type))){}

	bool IsNull() const { return !bool(m_ptr); }

	template<class U> bool Is() const {
		return m_tpIndex == std::type_index(typeid(U));
	}

	//将Any转换为实际的类型
	template<class U>
	U& AnyCast() {
		if (!Is<U>()) {
			std::cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << std::endl;
			throw std::logic_error{"bad cast"};
		}

		auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
		return derived->m_value;
	}

	Any& operator=(const Any& a) {
		if (m_ptr == a.m_ptr)
			return *this;

		m_ptr = a.Clone();
		m_tpIndex = a.m_tpIndex;
		return *this;
	}

    Any& operator=(Any&& a) {
        if (m_ptr == a.m_ptr)
            return *this;

        m_ptr = std::move(a.m_ptr);
        m_tpIndex = a.m_tpIndex;
        return *this;
    }

private:
	struct Base;
	typedef std::unique_ptr<Base> BasePtr;

	struct Base {
		virtual ~Base() {}
		virtual BasePtr Clone() const = 0;
	};

	template<typename T>
	struct Derived : Base {
		template<typename U>
		Derived(U && value) : m_value(std::forward<U>(value)) { }

		BasePtr Clone() const
		{
			return BasePtr(new Derived<T>(m_value));
		}

		T m_value;
	};

	BasePtr Clone() const {
		if (m_ptr != nullptr)
			return m_ptr->Clone();

		return nullptr;
	}

	BasePtr m_ptr;
	std::type_index m_tpIndex;
};

class MessageBus : NonCopyable {
public:
    //注册消息
	template<typename F>
	void attach(F&& f, const std::string& topic="") {
		auto func = to_function(std::forward<F>(f));
		add(topic, std::move(func));
	}

    // 发送消息
    template<typename R>
    void send(const std::string& topic="") {
        using func_type = std::function<R()>;
        std::string msg = topic + typeid(func_type).name();

        auto rg = m_map.equal_range(msg);
        for (iter it = rg.first; it!= rg.second; ++it) {
            auto f = it->second.AnyCast<func_type>();
            f();
        };
    }

    template<typename R, typename... Args>
    void send(Args&&... args, const std::string& topic="") {
        using func_type = std::function<R(Args...)>;
        std::string msg = topic + typeid(func_type).name();

        auto rg = m_map.equal_range(msg);
        for (iter it = rg.first; it!= rg.second; ++it) {
            auto f = it->second.AnyCast<func_type>();
            f(std::forward<Args>(args)...);
        };
    }


    // 移除某个主题
    template<typename R, typename... Args>
    void remove(const std::string& topic="") {
        using func_type = std::function<R(Args...)>;
        std::string msg = topic + typeid(func_type).name();
        int count = m_map.count(msg);

		if (count > 0) {
        	auto rg = m_map.equal_range(msg);
        	m_map.erase(rg.first, rg.second);                 //! 单个主题可能涉及多个消息，即多个function
		}
    }

private:
    //! 注册主题和消息
    template<typename F>
	void add(const std::string& topic, F&& f) {
		std::string msg = topic + typeid(F).name();
		m_map.emplace(std::move(msg), std::forward<F>(f));
	}
private:
    std::multimap<std::string, Any> m_map;
    typedef std::multimap<std::string, Any>::iterator iter;
};
